package arithmetic.sychronzied;

import groovy.json.JsonOutput;
import org.junit.jupiter.api.Test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author jiangfeng 2019/4/6 15:52
 *
 * sychronized 关键字
 */
public class Synchronized1 extends Thread {
    public static void main(String[] args) {


    }


    /**
     * isAlive 可以实现简单的回到主线程
     */
    @Test
    public void testSychronzied(){
        Thread t1 = new Synchronized1();
        Thread t2 = new Synchronized1();
        t1.start();
        t2.start();
        while (t1.isAlive()||t2.isAlive()){}
        System.out.println(111);
    }

    /**
     * jion 方法可实现相同效果
     */
    @Test
    public void testSychronized2(){
        Thread t1 = new Synchronized1();
        Thread t2 = new Synchronized1();
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
        }
        System.out.println(111);
    }

    @Test
    public void testSychronized3(){
        MyRunable myRunable = new MyRunable();
        Thread t1 = new Thread(myRunable);
        Thread t2 = new Thread(myRunable);
        t1.start();
        t2.start();
        while (t1.isAlive()||t2.isAlive()){}
        System.out.println(111);
    }

    @Test
    public void testSychronized4(){
        MyCallable myCallable =new MyCallable();
        FutureTask futureTask = new FutureTask(myCallable);
        Thread t1 = new Thread(futureTask);
        Thread t2 = new Thread(futureTask);
        t1.start();
        t2.start();
        try {
            Object o = futureTask.get();
            System.out.println(JsonOutput.toJson(o));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        while (t1.isAlive()||t2.isAlive()){}
        System.out.println(111);
    }


    /**
     * 测试synchronize的 关键字抛异常后自动释放锁
     */
    @Test
    public void testSychronized5(){
        MyRunable2 myRunable = new MyRunable2();
        Thread t1 = new Thread(myRunable);
        Thread t2 = new Thread(myRunable);
        t1.start();
        t2.start();
        while (t1.isAlive()||t2.isAlive()){}
        System.out.println(111);
    }

    /**
     * 测试Lock的写法
     * https://www.cnblogs.com/dolphin0520/p/3923167.html
     */
    @Test
    public void testLock6(){
        ReentrantLock lock =new ReentrantLock(); // 可重入锁
        lock.lock();
        try{
            // doSomething
        }finally {
            lock.unlock();
        }
    }


    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName()+"开始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"结束");
    }



}
class MyRunable implements Runnable {

    public void run() {
        synchronized (this){
            System.out.println(Thread.currentThread().getName()+"开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"结束");
        }
    }
}

class MyCallable implements Callable{

    @Override
    public Object call() throws Exception {
        Thread thread = Thread.currentThread();
        System.out.println(this);
        synchronized (this) {
            System.out.println(thread.getName() + "Callable 开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(thread.getName() + "Callable 结束");
        }
        return thread.getName();
    }
}

class MyRunable2 implements Runnable {

    public void run() {
        if(Thread.currentThread().getName().equals("Thread-1")){
            method1();
        }else {
            method2();
        }

    }
    public synchronized void method1(){
        System.out.println(Thread.currentThread().getName()+" method1开始");
        try {
            Thread.sleep(1000);
            //throw new Exception();
            throw new RuntimeException(); // 需要用 RuntimeException,不需要及时捕获处理

        } catch (InterruptedException e) {
            e.printStackTrace();
        } /*catch (Exception e) {
            System.out.println("method1 抛异常了,睡一秒");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }*/
        System.out.println("method1 抛异常了,睡一秒");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" method1结束");
    }
    public synchronized void method2(){
        System.out.println(Thread.currentThread().getName()+" method2开始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" method2结束");
    }

}
